//
//  GLFunctions.cpp
//  STDRenderSDK
//
//  Created by 陈学明 on 2023/3/12.
//

#include "STDSGLFunctions.hpp"

bool STDSGLFunctions::checkGlError(const char *op) {
    GXNS_GL(GLenum) error;
    while ((error = glGetError()) != GL_NO_ERROR) {
        LOG_ERROR("%s: glError: 0x%X", op, error);
        return false;
    }
    return true;
}

GLuint STDSGLFunctions::createTexture() {
    GLuint _tid;
    glGenTextures(1, &_tid);
    glBindTexture(GL_TEXTURE_2D, _tid);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint) GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint) GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLint) GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLint) GL_CLAMP_TO_EDGE);
    glBindTexture(GL_TEXTURE_2D, 0);
    return _tid;
}

GLuint STDSGLFunctions::createTexture(int _w, int _h, GXNS_GL(GLenum) _f) {
    if (_w * _h <= 0)
        return TEXTURE_NON;
    GLuint _tid;
    glGenTextures(1, &_tid);
    if (_tid > TEXTURE_NON) {
        glBindTexture(GL_TEXTURE_2D, _tid);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint) GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint) GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLint) GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLint) GL_CLAMP_TO_EDGE);
        glTexImage2D(GL_TEXTURE_2D, 0, (GLint) _f, _w, _h, 0, _f, GL_UNSIGNED_BYTE, 0);
        glBindTexture(GL_TEXTURE_2D, 0);
    }
    return _tid;
}

GLuint STDSGLFunctions::createTexture(void *_data, int _w, int _h) {
    GLuint _tid;
    glGenTextures(1, (GLuint *) &_tid);
    glBindTexture(GL_TEXTURE_2D, (GLuint) _tid);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint) GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint) GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLint) GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLint) GL_CLAMP_TO_EDGE);
    glTexImage2D(GL_TEXTURE_2D, 0, (GLint) GL_RGBA, _w, _h, 0, GL_RGBA, GL_UNSIGNED_BYTE, _data);
    return _tid;
}

void STDSGLFunctions::resetTextureFilter(unsigned int _tid, GXNS_GL(GLenum) _fmag, GXNS_GL(GLenum) _fmin) {
    glBindTexture(GL_TEXTURE_2D, _tid);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint) _fmag);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint) _fmin);
}

void STDSGLFunctions::resetTextureWrap(unsigned int _tid, GXNS_GL(GLenum) _wrapS, GXNS_GL(GLenum) _wrapT) {
    glBindTexture(GL_TEXTURE_2D, _tid);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLint) _wrapS);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLint) _wrapT);
}


void STDSGLFunctions::draw_ELE_POINTS(void *idx, int count, int start) {
    if(!idx) return;
    glDrawElements(GL_POINTS, count, GL_UNSIGNED_SHORT, idx);
}

void STDSGLFunctions::draw_ARR_POINTS(void *idx, int count, int start) {
    glDrawArrays(GL_POINTS, start, count);
}

void STDSGLFunctions::draw_ELE_TRI_STRIP(void *idx, int count, int start) {
    if(!idx) return;
    glDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_SHORT, idx);
}

void STDSGLFunctions::draw_ARR_TRI_STRIP(void *idx, int count, int start) {
    glDrawArrays(GL_TRIANGLE_STRIP, start, count);
}

void STDSGLFunctions::draw_ELE_TRIANGLES(void *idx, int count, int start) {
    if(!idx) return;
    glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, idx);
}

void STDSGLFunctions::draw_ARR_TRIANGLES(void *idx, int count, int start) {
    glDrawArrays(GL_TRIANGLES, start, count);
}

void STDSGLFunctions::draw_ELE_LINES(void *idx, int count, int start) {
    if(!idx) return;
    glDrawElements(GL_LINE_STRIP, count, GL_UNSIGNED_SHORT, idx);
}

void STDSGLFunctions::draw_ARR_LINES(void *idx, int count, int start) {
    glDrawArrays(GL_LINE_STRIP, start, count);
}

void STDSGLFunctions::draw_ELE_TRIFAN(void *idx, int count, int start) {
    if(!idx) return;
    glDrawElements(GL_TRIANGLE_FAN, count, GL_UNSIGNED_SHORT, idx);
}

void STDSGLFunctions::draw_ARR_TRIFAN(void *idx, int count, int start) {
    glDrawArrays(GL_TRIANGLE_FAN, start, count);
}
